using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.EventSystems;

namespace Game.UI
{
    // 自定义异步操作类，用于面板显示
    public class WindowShowOperation<T> : AsyncOperation where T : Window
    {
        public T ResultWindow { get; private set; }
        private bool _isDone = false;

        public new bool isDone => _isDone;

        public void Complete(T window)
        {
            ResultWindow = window;
            _isDone = true;
        }
    }

    /*
        UI管理器
        负责管理所有UI界面
        负责UI的显示和隐藏
        负责UI的切换
        扩展练习：
        1.假定窗口加载比较耗时,如何给玩家提供一个良好的加载体验
    */
    public class UIManager : UnityHelpers.SingletonBehaviour<UIManager>
    {
        [SerializeField]
        private GameObject panelContainer;

        [SerializeField]
        private GameObject dialogContainer;

        // ui prefab的地址
        [SerializeField]
        private string uiPrefabPath = "Assets/Addressables/UIPrefabs/";

        // 当前显示的面板
        private Panel _currentPanel;
        private EventSystem _eventSystem;

        // prefab的缓存
        private Dictionary<string, GameObject> _prefabCache = new Dictionary<string, GameObject>();

        // 当前显示的对话框列表
        private List<Dialog> _activeDialogs = new List<Dialog>();

        protected override void Awake()
        {
            base.Awake();
            _eventSystem = EventSystem.current;
        }

        private void DisableInput()
        {
            _eventSystem.enabled = false;
        }

        private void EnableInput()
        {
            _eventSystem.enabled = true;
        }

        #region Panel Methods

        public void ShowPanelAsync(string panelName, Action<Panel> onShow = null)
        {
            StartCoroutine(ShowWindowCoroutine<Panel>(panelName, panelContainer.transform, onShow,
                (panel) => { _currentPanel = panel; }));
        }

        public AsyncOperation ShowPanelAsync(string panelName)
        {
            DisableInput();
            try
            {
                var operation = new WindowShowOperation<Panel>();
                StartCoroutine(ShowWindowCoroutine<Panel>(panelName, panelContainer.transform, null,
                    (panel) => { _currentPanel = panel; }, operation));
                return operation;
            }
            finally
            {
                EnableInput();
            }
        }

        // 立即显示面板
        // 要求：资源必须已经加载
        public Panel ShowPanel(string panelName)
        {
            if (_prefabCache.TryGetValue(panelName, out GameObject uiPrefab))
            {
                // 关闭当前面板和所有对话框
                CloseCurrentPanelAndAllDialogs();

                var panel = CreateWindow<Panel>(uiPrefab, panelContainer.transform);
                _currentPanel = panel;
                return panel;
            }
            else
            {
                Debug.LogError($"UIManager: 预加载UI面板失败 - {panelName}");
                return null;
            }
        }

        #endregion

        #region Dialog Methods

        public Dialog ShowDialog(string dialogName)
        {
            if (_prefabCache.TryGetValue(dialogName, out GameObject uiPrefab))
            {
                var dialog = CreateWindow<Dialog>(uiPrefab, dialogContainer.transform);
                _activeDialogs.Add(dialog);
                return dialog;
            }
            else
            {
                Debug.LogError($"UIManager: 预加载UI对话框失败 - {dialogName}");
                return null;
            }
        }

        public AsyncOperation ShowDialogAsync(string dialogName)
        {
            DisableInput();
            try
            {
                var operation = new WindowShowOperation<Dialog>();
                StartCoroutine(ShowWindowCoroutine<Dialog>(dialogName, dialogContainer.transform, null,
                    (dialog) => { _activeDialogs.Add(dialog); }, operation));
                return operation;
            }
            finally
            {
                EnableInput();
            }
        }

        public void ShowDialogAsync(string dialogName, Action<Dialog> onShow = null)
        {
            StartCoroutine(ShowWindowCoroutine<Dialog>(dialogName, dialogContainer.transform, onShow,
                (dialog) => { _activeDialogs.Add(dialog); }));
        }

        // 对话框可以主动关闭
        public void CloseDialog(Dialog dialog)
        {
            if (_activeDialogs.Contains(dialog))
            {
                _activeDialogs.Remove(dialog);
                dialog.OnClose();
                Destroy(dialog.gameObject);
            }
        }

        #endregion

        #region Preload Methods

        public void Preload(string windowName, Action<GameObject> onLoad = null)
        {
            StartCoroutine(PreloadWindowCoroutine(windowName, onLoad));
        }

        // 检测是否加载完成
        public bool IsLoaded(string windowName)
        {
            return _prefabCache.ContainsKey(windowName);
        }

        #endregion

        #region Private Helper Methods

        // 通用的窗口创建方法
        private T CreateWindow<T>(GameObject prefab, Transform parent) where T : Window
        {
            var uiInstance = Instantiate(prefab, parent);
            uiInstance.SetActive(false);
            T window = uiInstance.GetComponent<T>();

            // 使用动态调用，因为OnCreate和OnShow方法在子类中定义
            window.OnCreate();
            uiInstance.SetActive(true);
            window.OnShow();

            return window;
        }

        // 通用的窗口显示协程
        private IEnumerator ShowWindowCoroutine<T>(string windowName, Transform parent,
            Action<T> onShow, Action<T> onWindowCreated, WindowShowOperation<T> operation = null) where T : Window
        {
            // 加载ui prefab
            GameObject uiPrefab = null;
            yield return StartCoroutine(LoadWindowPrefab(windowName, (prefab) => uiPrefab = prefab));
            if (uiPrefab == null)
            {
                operation?.Complete(null);
                yield break;
            }

            // 如果是Panel类型，关闭当前面板和所有对话框
            if (typeof(T) == typeof(Panel))
            {
                CloseCurrentPanelAndAllDialogs();
            }

            Debug.Log($"UIManager: 显示{typeof(T).Name} - {windowName}");

            // 创建窗口
            T window = CreateWindow<T>(uiPrefab, parent);
            onWindowCreated?.Invoke(window);

            // 调用回调
            onShow?.Invoke(window);

            // 完成异步操作
            operation?.Complete(window);
        }

        // 通用的预加载协程
        private IEnumerator PreloadWindowCoroutine(string windowName, Action<GameObject> onLoad = null)
        {
            if (_prefabCache.TryGetValue(windowName, out GameObject uiPrefab))
            {
                onLoad?.Invoke(uiPrefab);
                yield break;
            }

            var uiPrefabHandle = Addressables.LoadAssetAsync<GameObject>(uiPrefabPath + windowName + ".prefab");
            yield return uiPrefabHandle;
            if (uiPrefabHandle.Status == UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationStatus.Succeeded)
            {
                _prefabCache.Add(windowName, uiPrefabHandle.Result);
                onLoad?.Invoke(uiPrefabHandle.Result);

                // 日志
                Debug.Log($"UIManager: 预加载UI窗口成功 - {windowName}");
            }
            else
            {
                Debug.LogError($"UIManager: 预加载UI窗口失败 - {windowName}");
            }
        }

        // 加载窗口预制体
        private IEnumerator LoadWindowPrefab(string windowName, Action<GameObject> onLoad)
        {
            if (_prefabCache.TryGetValue(windowName, out GameObject uiPrefab))
            {
                onLoad?.Invoke(uiPrefab);
                yield break;
            }

            var uiPrefabHandle = Addressables.LoadAssetAsync<GameObject>(uiPrefabPath + windowName + ".prefab");
            yield return uiPrefabHandle;
            if (uiPrefabHandle.Status == UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationStatus.Succeeded)
            {
                uiPrefab = uiPrefabHandle.Result;
                _prefabCache.Add(windowName, uiPrefab);
                onLoad?.Invoke(uiPrefab);
            }
            else
            {
                Debug.LogError($"UIManager: 加载UI窗口失败 - {windowName}");
                onLoad?.Invoke(null);
            }
        }

        private void CloseCurrentPanelAndAllDialogs()
        {
            foreach (var dialog in _activeDialogs)
            {
                dialog.OnClose();
                Destroy(dialog.gameObject);
            }
            _activeDialogs.Clear();

            if (_currentPanel != null)
            {
                _currentPanel.OnClose();
                Destroy(_currentPanel.gameObject);
                _currentPanel = null;
            }
        }

        #endregion
    }
}


